home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sound / k005289.c < prev    next >
C/C++ Source or Header  |  2000-04-04  |  6KB  |  242 lines

  1. /***************************************************************************
  2.  
  3.     Konami 005289 - SCC sound as used in Bubblesystem
  4.  
  5.     This file is pieced together by Bryan McPhail from a combination of
  6.     Namco Sound, Amuse by Cab, Nemesis schematics and whoever first
  7.     figured out SCC!
  8.  
  9.     The 005289 is a 2 channel sound generator, each channel gets it's
  10.     waveform from a prom (4 bits wide).
  11.  
  12.     (From Nemesis schematics)
  13.  
  14.     Address lines A0-A4 of the prom run to the 005289, giving 32 bytes
  15.     per waveform.  Address lines A5-A7 of the prom run to PA5-PA7 of
  16.     the AY8910 control port A, giving 8 different waveforms. PA0-PA3
  17.     of the AY8910 control volume.
  18.  
  19.     The second channel is the same as above except port B is used.
  20.  
  21.     The 005289 has no data bus, so data values written don't matter.
  22.  
  23.     There are 4 unknown pins, LD1, LD2, TG1, TG2.  Two of them look to be
  24.     the selector for changing frequency.  The other two seem unused.
  25.  
  26. ***************************************************************************/
  27.  
  28. #include "driver.h"
  29.  
  30. #define FREQBASEBITS    16
  31.  
  32. /* this structure defines the parameters for a channel */
  33. typedef struct
  34. {
  35.     int frequency;
  36.     int counter;
  37.     int volume;
  38.     const unsigned char *wave;
  39. } k005289_sound_channel;
  40.  
  41. static k005289_sound_channel channel_list[2];
  42.  
  43. /* global sound parameters */
  44. static const unsigned char *sound_prom;
  45. static int stream,mclock,rate;
  46.  
  47. /* mixer tables and internal buffers */
  48. static INT16 *mixer_table;
  49. static INT16 *mixer_lookup;
  50. static short *mixer_buffer;
  51.  
  52. static int k005289_A_frequency,k005289_B_frequency;
  53. static int k005289_A_volume,k005289_B_volume;
  54. static int k005289_A_waveform,k005289_B_waveform;
  55. static int k005289_A_latch,k005289_B_latch;
  56.  
  57. /* build a table to divide by the number of voices */
  58. static int make_mixer_table(int voices)
  59. {
  60.     int count = voices * 128;
  61.     int i;
  62.     int gain = 16;
  63.  
  64.     /* allocate memory */
  65.     mixer_table = malloc(256 * voices * sizeof(INT16));
  66.     if (!mixer_table)
  67.         return 1;
  68.  
  69.     /* find the middle of the table */
  70.     mixer_lookup = mixer_table + (128 * voices);
  71.  
  72.     /* fill in the table - 16 bit case */
  73.     for (i = 0; i < count; i++)
  74.     {
  75.         int val = i * gain * 16 / voices;
  76.         if (val > 32767) val = 32767;
  77.         mixer_lookup[ i] = val;
  78.         mixer_lookup[-i] = -val;
  79.     }
  80.  
  81.     return 0;
  82. }
  83.  
  84.  
  85. /* generate sound to the mix buffer */
  86. static void K005289_update(int ch, INT16 *buffer, int length)
  87. {
  88.     k005289_sound_channel *voice=channel_list;
  89.     short *mix;
  90.     int i,v,f;
  91.  
  92.     /* zap the contents of the mixer buffer */
  93.     memset(mixer_buffer, 0, length * sizeof(INT16));
  94.  
  95.     v=voice[0].volume;
  96.     f=voice[0].frequency;
  97.     if (v && f)
  98.     {
  99.         const unsigned char *w = voice[0].wave;
  100.         int c = voice[0].counter;
  101.  
  102.         mix = mixer_buffer;
  103.  
  104.         /* add our contribution */
  105.         for (i = 0; i < length; i++)
  106.         {
  107.             int offs;
  108.  
  109.             c+=(long)((((float)mclock / (float)(f * 16))*(float)(1<<FREQBASEBITS)) / (float)(rate / 32));
  110.             offs = (c >> 16) & 0x1f;
  111.             *mix++ += ((w[offs] & 0x0f) - 8) * v;
  112.         }
  113.  
  114.         /* update the counter for this voice */
  115.         voice[0].counter = c;
  116.     }
  117.  
  118.     v=voice[1].volume;
  119.     f=voice[1].frequency;
  120.     if (v && f)
  121.     {
  122.         const unsigned char *w = voice[1].wave;
  123.         int c = voice[1].counter;
  124.  
  125.         mix = mixer_buffer;
  126.  
  127.         /* add our contribution */
  128.         for (i = 0; i < length; i++)
  129.         {
  130.             int offs;
  131.  
  132.             c+=(long)((((float)mclock / (float)(f * 16))*(float)(1<<FREQBASEBITS)) / (float)(rate / 32));
  133.             offs = (c >> 16) & 0x1f;
  134.             *mix++ += ((w[offs] & 0x0f) - 8) * v;
  135.         }
  136.  
  137.         /* update the counter for this voice */
  138.         voice[1].counter = c;
  139.     }
  140.  
  141.     /* mix it down */
  142.     mix = mixer_buffer;
  143.     for (i = 0; i < length; i++)
  144.         *buffer++ = mixer_lookup[*mix++];
  145. }
  146.  
  147. int K005289_sh_start(const struct MachineSound *msound)
  148. {
  149.     const char *snd_name = "K005289";
  150.     k005289_sound_channel *voice=channel_list;
  151.     const struct k005289_interface *intf = msound->sound_interface;
  152.  
  153.     /* get stream channels */
  154.     stream = stream_init(snd_name, intf->volume, Machine->sample_rate, 0, K005289_update);
  155.     mclock = intf->master_clock;
  156.     rate = Machine->sample_rate;
  157.  
  158.     /* allocate a pair of buffers to mix into - 1 second's worth should be more than enough */
  159.     if ((mixer_buffer = malloc(2 * sizeof(short) * Machine->sample_rate)) == 0)
  160.         return 1;
  161.  
  162.     /* build the mixer table */
  163.     if (make_mixer_table(2))
  164.     {
  165.         free (mixer_buffer);
  166.         return 1;
  167.     }
  168.  
  169.     sound_prom = memory_region(intf->region);
  170.  
  171.     /* reset all the voices */
  172.     voice[0].frequency = 0;
  173.     voice[0].volume = 0;
  174.     voice[0].wave = &sound_prom[0];
  175.     voice[0].counter = 0;
  176.     voice[1].frequency = 0;
  177.     voice[1].volume = 0;
  178.     voice[1].wave = &sound_prom[0x100];
  179.     voice[1].counter = 0;
  180.  
  181.     return 0;
  182. }
  183.  
  184.  
  185. void K005289_sh_stop(void)
  186. {
  187.     free (mixer_table);
  188.     free (mixer_buffer);
  189. }
  190.  
  191. /********************************************************************************/
  192.  
  193. static void k005289_recompute(void)
  194. {
  195.     k005289_sound_channel *voice = channel_list;
  196.  
  197.     stream_update(stream,0);     /* update the streams */
  198.  
  199.     voice[0].frequency = k005289_A_frequency;
  200.     voice[1].frequency = k005289_B_frequency;
  201.     voice[0].volume = k005289_A_volume;
  202.     voice[1].volume = k005289_B_volume;
  203.     voice[0].wave = &sound_prom[32 * k005289_A_waveform];
  204.     voice[1].wave = &sound_prom[32 * k005289_B_waveform + 0x100];
  205. }
  206.  
  207. WRITE_HANDLER( k005289_control_A_w )
  208. {
  209.     k005289_A_volume=data&0xf;
  210.     k005289_A_waveform=data>>5;
  211.     k005289_recompute();
  212. }
  213.  
  214. WRITE_HANDLER( k005289_control_B_w )
  215. {
  216.     k005289_B_volume=data&0xf;
  217.     k005289_B_waveform=data>>5;
  218.     k005289_recompute();
  219. }
  220.  
  221. WRITE_HANDLER( k005289_pitch_A_w )
  222. {
  223.     k005289_A_latch = 0x1000 - offset;
  224. }
  225.  
  226. WRITE_HANDLER( k005289_pitch_B_w )
  227. {
  228.     k005289_B_latch = 0x1000 - offset;
  229. }
  230.  
  231. WRITE_HANDLER( k005289_keylatch_A_w )
  232. {
  233.     k005289_A_frequency = k005289_A_latch;
  234.     k005289_recompute();
  235. }
  236.  
  237. WRITE_HANDLER( k005289_keylatch_B_w )
  238. {
  239.     k005289_B_frequency = k005289_B_latch;
  240.     k005289_recompute();
  241. }
  242.